<?php 

function TruncateStr($str, $max_len) {
    if (mb_strlen($str, 'utf-8') > $max_len) {
       return mb_substr($str, 0, $max_len - 1, 'utf-8') . '...';
    }
    return $str;
}

function GetArticleMeta($aid) {
  $meta = apc_fetch(sprintf('article-meta-%d', $aid));
  if (!$meta || $meta['a_category'] < 0) {
    $sql=sprintf("SELECT a.id AS a_id, a.title AS a_title, a.url AS a_url, a.category AS a_category, a.create_time AS a_create_time,
      u.id AS u_id, u.name AS u_name, u.title AS u_title, u.url AS u_url
      FROM articles AS a, authors AS u WHERE a.author = u.id AND a.id = %d", $aid);
    // print $sql;
    $result = mysql_query($sql);
    $meta = mysql_fetch_array($result);
    if ($meta && $meta['a_title'] && $meta['a_category'] >= 0) {
      apc_add(sprintf('article-meta-%d', $aid), $meta, 3600 * 2);
    }
  }
  return $meta;
}

function GetArticleContent($article_id) {
  $sql=sprintf("SELECT content FROM article_content WHERE id = %d", $article_id);
  $result = mysql_query($sql);
  $row = mysql_fetch_array($result);

  $ret = '';
  if ($row) {
    $ret = $row['content'];
  }
  return $ret;
}

// $href_fmt: XXXX&s=%d&XXXX
function CommonPageNav($total_pages, $count_per_page, $current_page, $max_neighbors, $href_fmt) {
  if ($total_pages <= 0) {
    return;
  }
  $i = $current_page - $max_neighbors;
  if ($i < 1) {
    $i = 1;
  }
  $last_page = $current_page + $max_neighbors;
  if ($last_page > $total_pages) {
    $last_page = $total_pages;
  }

  $url_sep = strstr($href_fmt, '?') ? '&' : '?';
  print('<div class="page-nav">');
  if ($current_page > 1) {
    if ($i > 4) {
      $prev_mid = ($i + 1) / 2;
      printf('<a class="page-nav" href="' . $href_fmt . $url_sep . 'f=prev">最新</a> ... ', 1);
      printf('<a class="page-nav" href="' . $href_fmt . $url_sep . 'f=prev">%d</a> ... ', $prev_mid, $prev_mid);
    } else {
      $prev = $current_page - 1;
      printf('<a class="page-nav" href="' . $href_fmt . $url_sep . 'f=prev">上一页</a> ', $prev);
    }
  }

  for(; $i <= $last_page; ++$i) {
    if($i == $current_page) {
      printf('<a class="page-nav current" href="' . $href_fmt . '">%d</a> ', $i, $i, $i);
    } else {
      printf('<a class="page-nav" href="' . $href_fmt . '">%d</a> ', $i, $i, $i);
    }
  }

  if ($current_page < $total_pages) {
    if ($last_page + 3 < $total_pages) {
      $next_mid = ($last_page + $total_pages + 1) / 2;
      printf(' ... <a class="page-nav" href="' . $href_fmt . $url_sep . 'f=next">%d</a> ', $next_mid, $next_mid);
      printf(' ... <a class="page-nav" href="' . $href_fmt . $url_sep . 'f=next">最旧</a> ', $total_pages);
    } else {
      $next = $current_page + 1;
      printf('<a class="page-nav" href="' . $href_fmt . $url_sep . 'f=next">下一页</a> ', $next);
    }
  }
  printf('<span style="font-size:90%%;color:#a9a;"> (共%d页)</span>', $total_pages);
  print('</div>');
}

function TruncateHtml($text, $length = 100, $ending = '...') {
  // if the plain text is shorter than the maximum length, return the whole text
  if (mb_strlen(preg_replace('/<.*?>/', '', $text), 'utf-8') <= $length) {
    return $text;
  }

  // print $text;

  preg_match_all('/(<.+?>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER);
  $total_length = mb_strlen($ending, 'utf-8');
  $open_tags = array();
  $truncate = '';
  foreach ($lines as $line) {
    if (!empty($line[1])) {
      // print $line[1];
      if (preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $line[1])) {
         // do nothing
      } else if (preg_match('/^<\s*([^\/\s>!]+).*?>$/s', $line[1], $tag_matchings)) {
        // if tag is an opening tag, add tag to the beginning of $open_tags list
        array_unshift($open_tags, strtolower($tag_matchings[1]));
      } else if (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line[1], $tag_matchings)) {
        // closing tag, delete tag from $open_tags list
        $pos = array_search($tag_matchings[1], $open_tags);
        if ($pos !== false) {
          unset($open_tags[$pos]);
        }
      }
      $truncate .= $line[1];
    }

    // calculate the length of the plain text part of the line; handle entities as one character
    $content_length = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line[2]));
    if ($total_length + $content_length> $length) {
      $left = $length - $total_length;
      $entities_length = 0;
      // search for html entities
      if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', $line[2], $entities, PREG_OFFSET_CAPTURE)) {
        // calculate the real length of all entities in the legal range
        foreach ($entities[0] as $entity) {
          if ($entity[1]+1-$entities_length <= $left) {
            $left--;
            $entities_length += mb_strlen($entity[0], 'utf-8');
          } else {
            // no more characters left
            break;
          }
        }

        $truncate .= mb_substr($line[2], 0, $left+$entities_length, 'utf-8');
        break;
      } else {
        $truncate .= $line[2];
        $total_length += $content_length;
      }

      if($total_length >= $length) {
        break;
      }
    } else {
      $truncate .= $line[2];
      $total_length += $content_length;
    }
  }
  $truncate .= $ending;
  foreach ($open_tags as $tag) {
    $truncate .= '</' . $tag . '>';
  }
  return $truncate;
}

function InitThrift() {
  if (!$GLOBALS['THRIFT_ROOT']) {
    $GLOBALS['THRIFT_ROOT'] = '/opt/php/lib/php/thrift-0.5.0';
    
    // Load up all the thrift stuff
    require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';
    require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';
    require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';
    require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
  }
}

$g_related_client = null;
function GetRelated($article_id) {
  if (!$g_related_client) {
    try {
      InitThrift();
      // Load the package that we autogenerated for this tutorial
      require_once './gen-php/RelatedRecomm/RelatedRecomm.php';
      require_once './gen-php/RelatedRecomm/RelatedRecomm_types.php';

      // Create a thrift connection (Boiler plate)
      $socket = new TSocket('127.0.0.1', '9091');
      $transport = new TBufferedTransport($socket);
      $protocol = new TBinaryProtocol($transport);
    
      $g_related_client = new RelatedRecommClient($protocol);
      $transport->open();
    } catch (TException $tx) {}
  }
  if ($g_related_client) {
    return $g_related_client->GetRelated($article_id);
  }
  return array();
}

$g_search_client = null;
function Search($text, $start, $count) {
  $search_res = null;
  if (!$g_search_client) {
    try {
      InitThrift();
      require_once './gen-php/SearchEngine/SearchEngine.php';
      require_once './gen-php/SearchEngine/SearchEngine_types.php';
      $socket = new TSocket('127.0.0.1', '10093');
      $transport = new TBufferedTransport($socket);
      $protocol = new TBinaryProtocol($transport);
    
      $g_search_client = new SearchEngineClient($protocol);
      $transport->open();
    } catch (TException $tx) {}
  }
  // print $g_search_client . '--------------'; 
  if ($g_search_client) {
    $search_res = $g_search_client->Search($text, $start, $count);
  }
  return $search_res;
}

function GetCategoryMap() {
  $category_map = null;
  if (!($category_map = apc_fetch('category-map'))) {
    $category_map = array();
    $sql = sprintf("SELECT id, name, title FROM categories;");
    $result = mysql_query($sql);
    while($r = mysql_fetch_array($result)) {
      $category_map[$r['id']] = $r;
    }
    apc_add('category-map', $category_map, 3600);
  }
  return $category_map;
}

function ArticlePreview($article_id) {
  $article_meta = GetArticleMeta($article_id);
  $content = GetArticleContent($article_id);
  if (!$article_meta || !$content) {
    return;
  }
  printf('<h3 class="article-title" style="font-weight:bold;line-height:22px;font-size:14px;"><a style="text-decoration:underline;" target="_blank" title="%s" href="/a/%d.html?f=title">%s</a></h3>', $article_meta['a_create_time'], $article_id, $article_meta['a_title']);

  // printf('%s', TruncateHtml($content, 620, '...'));
  // 
  // printf('<div style="border-top:1px solid #c9c9c9;padding:2px;">');
  // $cmap = GetCategoryMap();
  // printf('类别 : <a href="/cat%d/">%s</a> ', $article_meta['a_category'], $cmap[$article_meta['a_category']]['name']);
  // printf('&nbsp;作者 : <a title="%s:%s" href="/u%d/">%s</a>', $article_meta['u_name'], $article_meta['u_title'],
  //     $article_meta['u_id'], $article_meta['u_name']);
  // 
  // printf('&nbsp; <span style="font-size:12px;">%s </span>', $article_meta['a_create_time']);  
  // printf('&nbsp; <a style="font-size:12px;line-height:21px;" href="/a/%d.html?f=readall">阅读全文&gt;&gt;</a>', $article_id);
  // printf('</div>');
}

?>

